iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0
自我挑戰組

Terraform 繁體中文系列 第 9

Day9-【入門教程】Terraform代碼的書寫—輸出值及局部值

  • 分享至 

  • xImage
  •  

原簡體中文教程連結: Introduction.《Terraform入門教程》


1.4.4.1. 輸出值

我們在介紹輸入變數時提到過,如果我們把一組 Terraform 程式碼想像成一個函數,那麼輸入變數就是函數的入參;函數可以有入參,也可以有回傳值,同樣的,Terraform 程式碼也可以有回傳值,這就是輸出值。

大部分語言的函數只支援無回傳值或是單回傳值,但是 Terraform 支援多回傳值。在目前模組 apply 一段 Terraform 程式碼,執行成功後命令列會輸出程式碼中定義的回傳值。另外我們也可以透過 terraform output 指令來輸出目前模組對應的狀態檔中的回傳值。

1.4.4.1.1. 輸出值的聲明

輸出值的聲明使用輸出區塊,例如:

output "instance_ip_addr" {
  value = aws_instance.server.private_ip
}

output 關鍵字後面緊接的就是輸出值的名稱。在目前模組內的所有輸出值的名字都必須是唯一的。output 區塊內的 value 參數即為輸出值,它可以像上面的範例裡那樣某個 resource 的輸出屬性,也可以是任意合法的表達式。

輸出值只有在執行 terraform apply 後才會被計算,光是使用 terraform plan 並不會計算輸出值。

Terraform 程式碼中無法引用本目錄下定義的輸出值。

output 區塊還有一些可選的屬性:

1.4.4.1.1.1. description

output "instance_ip_addr" {
  value       = aws_instance.server.private_ip
  description = "The private IP address of the main server instance."
}

與輸入變數的 description 類似,我們不再贅述。

1.4.4.1.1.2. sensitive

一個輸出值可以標記 sensitivetrue,表示該輸出值含有敏感資訊。被標記 sensitive 的輸出值只是在執行 terraform apply 指令成功後會印出""以取代真實的輸出值,執行 terraform output 時也會輸出 "\",但仍可以透過執行 terraform output -json 看到實際的敏感值。

需要注意的是,標記為 sensitive 輸出值仍然會被記錄在狀態檔案中,任何有權限讀取狀態檔案的人仍然可以讀取到敏感資料。

1.4.4.1.1.3. depends_on

關於 depends_on 的內容將在 resource 章節中詳細介紹,所以這裡我們只是粗略地介紹一下。

Terraform 會解析程式碼所定義的各種 data、resource,以及他們之間的依賴關係,例如,建立虛擬機器時用的 image_id 參數是透過 data 查詢而來的,那麼虛擬機器實例就依賴這個鏡像的 data, Terraform 會先建立 data,得到查詢結果後,再建立虛擬機器 resource。一般來說,data、resource 之間的建立順序是由 Terraform 自動計算的,不需要程式碼的編寫者明確指定。但有時有些依賴關係無法透過分析程式碼得出,這時我們可以在程式碼中透過 depends_on 明確聲明依賴關係。

一般 output 很少會需要明確依賴某些資源,但有一些特殊場景,例如在當前程式碼中呼叫一個模組(可以理解成調用另一個目錄中的 Terraform 程式碼創建一些資源)時,呼叫者希望在模組資源全部創建完畢以後才繼續後續的創建工作,這時我們可以為模組設計一個 output,透過 depends_on 明確聲明依賴關係,以確保該 output 必須在所有模組資源成功創建以後才能被讀取,這樣我們就可以在模組尺度上控制資源的建立順序。

depends_on 的用法如下:

output "instance_ip_addr" {
  value       = aws_instance.server.private_ip
  description = "The private IP address of the main server instance."

  depends_on = [
    # Security group rule must be created before this IP address could
    # actually be used, otherwise the services will be unreachable.
    aws_security_group_rule.local_access,
  ]
}

我們不鼓勵針對 output 定義 depends_on,只能作為最後的手段加以應用。如果不得不針對 output 定義 depends_on,請務必透過註解說明原因,方便後人進行維護。

1.4.4.1.1.4. precondition

output 區塊從 Terraform v1.2.0 開始也可以包含一個 precondition 區塊。

output 塊上的 precondition 對應於 variable 塊中的 validation 塊。validation 區塊檢查輸入變數值是否符合模組的要求,precondition 確保模組的輸出值符合某種要求。我們可以透過 precondition 來防止 Terraform 把一個不合法的處置值寫入狀態檔。我們可以在適當的場景下通過 precondition 來保護上一次 apply 留下的合法的輸出值。

Terraform 在計算輸出值的 value 表達式之前執行 precondition 檢查,這可以防止 value 表達式中的潛在錯誤被激發。


1.4.5.1. 局部值

有時我們會需要用一個比較複雜的表達式計算某一個值,並且重複使用之,這時我們把這個複雜表達式賦予一個局部值,然後反覆引用該局部值。如果說輸入變數相當於函數的入參,輸出值就相當於函數的回傳值,那麼局部值就相當於函數內定義的局部變數。

局部值透過 locals 區塊定義,例如:

locals {
  service_name = "forum"
  owner        = "Community Team"
}

一個 locals 區塊可以定義多個局部值,也可以定義任意多個 locals 區塊。賦給局部值的可以是更複雜的表達式,也可以是其他 data、resource 的輸出、輸入變量,甚至是其他的局部值:

locals {
  # Ids for multiple sets of EC2 instances, merged together
  instance_ids = concat(aws_instance.blue.*.id, aws_instance.green.*.id)
}

locals {
  # Common tags to be assigned to all resources
  common_tags = {
    Service = local.service_name
    Owner   = local.owner
  }
}

引用局部值的表達式是 local.<NAME>(注意,雖然局部值定義在 locals 區塊內,但引用是務必使用 local 而不是 locals),例如:

resource "aws_instance" "example" {
  # ...

  tags = local.common_tags
}

局部值只能在同一模組內的程式碼中引用。

局部值可以幫助我們避免重複複雜的表達式,提升程式碼的可讀性,但如果過度使用也有可能增加程式碼的複雜度,使得程式碼的維護者更難理解所使用的表達式和值。適度使用局部值,僅用於重複引用相同複雜表達式的場景,未來當我們需要修改該表達式時局部值將使得修改變得相當輕鬆。


原簡體中文教程連結: Introduction.《Terraform入門教程》


上一篇
Day8-【入門教程】Terraform代碼的書寫—配置語法及輸入變數
下一篇
Day10-【入門教程】資源
系列文
Terraform 繁體中文25
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言